<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>index</title>
    <style>
        body {
            margin: 0;
        }
        #root {
            /*float: right;*/
            width: 100%;
        }
        #left {
            width: 20%;
        }
        #center {
            width: 60%;
        }
        #right {
            width: 20%;
        }
        .inline {
            float: right;
            text-align: right;
            display: inline-block;
        }
    </style>
</head>
<body>
<div id="root">
    <h1>Fuck Compojure</h1>
    <div class="inline" id="left">left</div>
    <div class="inline" id="center">center</div>
    <div class="inline" id="right">right</div>
</div>

<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>

<script>
    
        const kirito = {
            hp: 100,
            name: "kirito",
            str: 10,
        }
    
        const monster = {
            hp: 100,
            def: 10,
        }
    
        const skills = {
            "angry_chop": function (src) {
                return damage_skill(src.str * 0.5 + 10)
            }
        }
    
        const buffs = {
            "once_shield": {
                before_affect: function ([skill, src, tar]) {
                    console.log('Once_shield enter')
                    if (is_damage_skill(skill)) {
                        skill = safe_skill(skill)
                    }
                    return [skill, src, tar]
                }
            }
        }
    
    
        function is_damage_skill(skill) {
            return skill.damage != null
        }
    
        function safe_skill(skill) {
            skill.damage = 0
            return skill
        }
    
        function damage_skill(damage) {
            return { damage }
        }
    
        function do_action([skill_maker_id, src, tar]) {
            const skill = (skills[skill_maker_id])(src)
            return action([skill, src, tar])
        }
    
        function action(action_obj_origin) {
            let action_obj = action_obj_origin
            action_obj = before_spell(action_obj)
            action_obj = after_spell(action_obj)
            action_obj = before_affect(action_obj)
            action_obj = affect(action_obj)
            action_obj = after_affected(action_obj)
            return action_obj
        }
    
        function safe_map(fn, list) {
            if (list != null) {
                return list.map(fn)
            }
            return
        }
    
        function before_spell([skill, src, tar]) {
            if (src.buffs) {
                src.buffs.map((buff) => {
                    if (buff.before_spell != null) {
                        [skill, src, tar] = buff.before_spell([skill, src, tar])
                    }
                })
            }
            return [skill, src, tar]
        }
    
        function after_spell([skill, src, tar]) {
            if (src.buffs) {
                src.buffs.map((buff) => {
                    if (buff.after_spell != null) {
                        [skill, src, tar] = buff.after_spell([skill, src, tar])
                    }
                })
            }
            return [skill, src, tar]
        }
    
        function before_affect([skill, src, tar]) {
            console.log('start')
            if (tar.buffs) {
                console.log('Has buffs')
                tar.buffs.map((buff) => {
                    if (buff.before_affect != null) {
                        console.log('Has before_affect')
                        [skill, src, tar] = buff.before_affect([skill, src, tar])
                    }
                })
            }
            console.log('end')
            return [skill, src, tar]
        }
    
        function after_affected([skill, src, tar]) {
            if (tar.buffs) {
                tar.buffs.map((buff) => {
                    if (buff.after_affected != null) {
                        [skill, src, tar] = buff.after_affected([skill, src, tar])
                    }
                })
            }
            return [skill, src, tar]
        }
    
        function affect(action_obj) {
            action_obj = damage(action_obj)
            action_obj = affect_direct(action_obj)
            return action_obj
        }
    
        function affect_direct([skill, src, tar]) {
            if (skill.affect_direct != null) {
                [skill, src, tar] = skill.affect_direct([skill, src, tar])
            }
            return [skill, src, tar]
        }
    
        function damage([skill, src, tar]) {
            tar.hp -= (skill.damage - tar.def)
            return [skill, src, tar]
        }
    
        function add_buff(buff_id, tar) {
            if (tar.buffs == null) {
                tar.buffs = []
            }
            tar.buffs.push(buffs[buff_id])
        }
    
        (function start() {
            add_buff("once_shield", monster)
            console.log(kirito, monster)
            let [new_skill, new_kirito, new_monster] = do_action(["angry_chop", kirito, monster])
            console.log(kirito, monster)
        }())
    </script>
</body>
</html>
